#include <PageTable.h>
#include <kstdio.h>
#include <asm.h>

PageTable::PageTable(uint32 h, page_t *ptr){
	height = h;
	root = ptr;
}

PageTable::PageTable(PageTable *from_tlb, uint32 flag){
	height = from_tlb->getHeight();
	root = (page_t *)_va(zone_normal->allocFrame(0));
	
	uint32 i, j, z = 0;
	for(i = 0; i < 1024; ++i){root[i] = 0;}
	
	page_t *pmd_from, *pmd_to;
	
	//Копируем часть таблицы отвечающу за область ядра
	i = _pgd_i(0xc0000000);
	for(z = 0; z < 256; ++i, ++z){
		root[i] = from_tlb->root[i];
	}
	/*
	for(z = 0; z < 1024; z++){
		if(from_tlb->root[z] > 0){
			kprintf("[%i] %X;  ", z, from_tlb->root[z]);
		}
	}
	*/
	//for(;;);
	//memcpy(&from_tlb->root[i], &root[i], 1024);
	
	kprintf("Copy user space PT\n");
	//Для памяти пользовательского пространства создаем свои каталоги страниц
	if(testbit(flag, PT_COPY_AS)){
		kprintf("flag\n");
		for(i = 0; i < 768; ++i){
			if(from_tlb->root[i] > 0){
				kprintf("PTE[%i]\n", i);
				pmd_from = (page_t *)(from_tlb->root[i] & (~PG_ADDR_MASK));
				pmd_to = (page_t *)zone_normal->allocFrame(0);
				root[i] = (from_tlb->root[i] & PG_ADDR_MASK) | (addr_t)pmd_to;
				kprintf("TestBit Flag: %X\n", flag);
				if(testbit(flag, PT_MARK_RO - 1)){
					for(j = 0; j < 1024; j++){
						//kprintf("j[%i]: %X,", j, pmd_from);
						((addr_t *)_va(pmd_from))[j] = clrbit(((addr_t *)_va(pmd_from))[j], PTE_RW);
						uint32 flag = ((addr_t *)_va(pmd_from))[j] & 0x7;
						if(flag)
						kprintf("Flag = %X\n", flag);
						((addr_t *)_va(pmd_to))[j] = ((addr_t *)_va(pmd_from))[j];
						//for(;;);
					}
					//for(;;);
				}else{
					kprintf("Not Marked\n");
					memcpy(_va(pmd_from), _va(pmd_to), 4096);
				}
			}else{
				root[i] = 0;
			}
		}
		//for(;;);
	}
	/*
	for(z = 0; z < 1024; z++){
		if(root[z] != 0) kprintf("[%i]%X, ", z, root[z]);
	}
	*/
	//for(;;);
}

void PageTable::mapPage(addr_t addr, Frame *frm, uint32 flags){
	uint32 pgd_idx = _pgd_i(addr), pmd_idx = _pmd_i(addr);
	page_t *pmd;
	kprintf("ROOT PD: %X\n", root);
	if(root[pgd_idx] == 0){
		root[pgd_idx] = (page_t )zone_normal->allocFrame(0) | 0x7;
	}
	pmd = (page_t *) _va((root[pgd_idx] & (~PG_ADDR_MASK)));
	kprintf("PMD_ADDR: %X\n", pmd);
	pmd[pmd_idx] = (page_t) _frm_to_addr(frm) | flags;
}




